/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Domain;

import Domain.Player.Disc;
import Domain.Player.Human;
import Domain.Player.Player;
import Domain.Player.PlayerType;
import Main.AppConstants;
import java.io.Serializable;
import java.util.Random;
import javax.security.auth.login.AppConfigurationEntry;

/**
 *
 * @author sa11
 */
public class GameManager implements Serializable{

    private GameGrid gameGrid;
    private DomainController logicController;
    private Player player1;
    private Player player2;
    private int currentPlayerNum;
    private boolean debug = false;

    public GameManager(DomainController logicController, GameGrid gameGrid) {
        this.gameGrid = gameGrid;
        this.logicController = logicController;
    }

    /**
     * Starts the game by executing the GameLoop class
     */
    public void startGame() {
        // System.out.println("starting");
        gameLoop();

    }

    /**
     * GameLoop class utilizing the SwingWorker class
     */
    private void gameLoop() {
        // System.out.println("starting");
        new Thread(new Runnable() {

            @Override
            public void run() {
                int rewardXtra = 0;
                currentPlayerNum = 1;
                // System.out.println("in run");
                gameGrid = logicController.getGameGrid();

                while (!hasEnded()) {
                    rewardXtra++;
                    logicController.setCurrentPlayerFrameName(getCurrentPlayer());
                    makeNextMove();
                }
                // System.out.println("over");
                AppConstants.numberOfRounds--;
                Player winner = getWinner();
                
                if (player1 == winner) {
                    AppConstants.player1Result = 1;// 10-rewardXtra;
                    AppConstants.player2Result = -1;// -(rewardXtra/2);
                } else if (player2 == winner) {
                    AppConstants.player1Result = -1;// -(rewardXtra/2);
                    AppConstants.player2Result = 1; // 10-rewardXtra;
                } else {
                    AppConstants.player1Result = 1;
                    AppConstants.player2Result = 1;
                }

                if (player1 instanceof Human || player2 instanceof Human) {
                    if (winner != null) {
                        logicController.presentWinnerBoard();
                        logicController.showWinnerDialog(winner);
                    } else if (gameGrid.isTie()) {
                        logicController.showDrawnDialog();
                    }
                }

                player1.updateHash(AppConstants.player1Result);
                player2.updateHash(AppConstants.player2Result);
                if (AppConstants.numberOfRounds > 0) {
                    if(player1 == winner){
                        player1.updateHash(-101);
                    } else if(player2 == winner){
                        player1.updateHash(-101);
                    }
                    logicController.resetGameGrid();
                    gameLoop();
                } else{
                    player1.updateHash(-1337);
                    player2.updateHash(-1337);
                }
            }
        }).start();
    }

    /**
     * Add players to the game
     *
     * @param player1
     * @param player2
     */
    public void addPlayers(Player player1, Player player2) {
        this.player1 = player1;
        this.player2 = player2;

        randomizeStartPlayer();
    }

    /**
     * Randomize start player
     */
    public void randomizeStartPlayer() {
        if (player1 != null && player2 != null) {
            currentPlayerNum = (new Random().nextInt() % 2 == 0 ? 1 : 2);
        }
    }

    /**
     * Returns a Player object corresponding to playerNum
     */
    public Player getPlayer(int playerNum) {
        return (playerNum % 2 == 0 ? player2 : player1);
    }

    /**
     * Returns the Player object for the current player
     */
    public Player getCurrentPlayer() {
        return (currentPlayerNum % 2 == 0 ? player2 : player1);
    }

    /**
     * Change the current player
     */
    public void changeCurrentPlayer() {
        currentPlayerNum = getCurrentPlayer().getDiscID().
                equals(player1.getDiscID()) ? 2 : 1;
    }

    /**
     * Executes the next move
     */
    public boolean makeNextMove() {
        Square move = logicController.getNextMove();
        int row = move.getX();
        int column = move.getY();

        if (gameGrid.isValidMove(column, row)) {
            gameGrid.setDisc(row, column, getCurrentPlayer().getDiscID());

            logicController.addDisc(row, column);
            changeCurrentPlayer();
            return true;
        } else {
            System.out.println("invalid move");
        }
        return false;
    }

    /**
     * Returns true if the current game has ended
     */
    private boolean hasEnded() {
        return gameGrid.isTie() || gameGrid.hasWon();
    }

    /**
     * Returns the winner as a Player object, null if none
     */
    private Player getWinner() {
        if (gameGrid.getWinner() != Disc.NONE) {
            return (player1.getDiscID() == gameGrid.getWinner()
                    ? player1 : player2);
        }
        return null;
    }

    public void setDebug(boolean debug) {
        this.debug = (this.debug == debug) ? invers(debug) : debug;
    }

    private boolean invers(boolean debug) {
        return debug == true ? false : true;
    }

    public void setGameGrid(GameGrid gameGrid) {
        this.gameGrid = gameGrid;
    }
}
